package com.nowcoder.topic.dp.middle;

/**
 * NC353 回文子串的数量
 * @author d3y1
 */
public class NC353{
    /**
     * 代码中的类名、方法名、参数名已经指定，请勿修改，直接返回方法规定的值即可
     *
     *
     * @param str string字符串
     * @return int整型
     */
    public int Substrings (String str) {
//        return solution1(str);
        return solution2(str);
//        return solution3(str);
    }

    /**
     * 模拟法
     * @param str
     * @return
     */
    private int solution1(String str){
        int count = 0;
        for(int i=0; i<str.length(); i++){
            for(int j=0; j<=i; j++){
                if(str.charAt(j) == str.charAt(i)){
                    if(isPalindrome(str.substring(j,i+1))){
                        count++;
                    }
                }
            }
        }

        return count;
    }

    /**
     * 动态规划
     *
     * dp[j][i]表示子串(从j到i)是否为回文串
     *
     *            { dp[j+1][i-1] , str.charAt(j) == str.charAt(i)
     * dp[j][i] = {
     *            { false        , str.charAt(j) != str.charAt(i)
     *
     * @param str
     * @return
     */
    private int solution2(String str){
        int len = str.length();
        boolean[][] dp = new boolean[len][len];

        int count = 0;
        for(int i=0; i<len; i++){
            for(int j=0; j<=i; j++){
                if(str.charAt(j) == str.charAt(i)){
                    if(i-j <= 1){
                        count++;
                        dp[j][i] = true;
                    }else{
                        if(dp[j+1][i-1]){
                            count++;
                            dp[j][i] = true;
                        }
                    }
                }
            }
        }

        return count;
    }

    /**
     * 双指针中心扩展法
     * @param str
     * @return
     */
    private int solution3(String str){
        int len = str.length();
        int count = 0;

        for(int i=0; i<len; i++){
            // 奇回文
            count += expand(str, i, i);
            // 偶回文
            count += expand(str, i, i+1);
        }

        return count;
    }

    /**
     * 中心扩展法
     * @param str
     * @param i
     * @param j
     * @return
     */
    private int expand(String str, int i, int j){
        int count = 0;
        while(0<=i && j<str.length() && str.charAt(i--)==str.charAt(j++)){
            count++;
        }

        return count;
    }

    /**
     * 是否回文串
     * 比checkPalindrome()效率高
     * @param str
     * @return
     */
    private boolean isPalindrome(String str){
        for(int i=0,j=str.length()-1; i<=j; i++,j--){
            if(str.charAt(i) != str.charAt(j)){
                return false;
            }
        }

        return true;
    }

    /**
     * 校验回文串
     * @param str
     * @return
     */
    private boolean checkPalindrome(String str){
        StringBuilder sb = new StringBuilder(str);
        return sb.reverse().toString().equals(str);
    }
}